<template>
  <el-form
    ref="refFormRefs"
    :class="['ls-form', { 'is-inline': inline, 'ls-show-all': showAll }]"
    inline
    :label-width="labelWidth"
    :model="model"
    v-bind="$attrs"
  >
    <el-row class="ls-search-from" ref="rfmediaRow">
      <!-- $attrs  props 没有接收的属性 -->
      <el-col
        class="ls-search-col-custom"
        v-for="(item, index) in config"
        :key="index"
        :class="{ 'ls-show-col': !showAll }"
        :xs="getLineWidth(defaultMediaVal.xs, index)"
        :sm="getLineWidth(defaultMediaVal.sm, index)"
        :md="getLineWidth(defaultMediaVal.md, index)"
        :lg="getLineWidth(defaultMediaVal.lg, index)"
        :xl="getLineWidth(defaultMediaVal.xl, index)"
      >
        <!-- 插槽 -->
        <slot v-if="item.type === 'itemSlot'" :name="item.slotName" v-bind="item"></slot>
        <!-- 二级头部 -->
        <div v-else-if="item.type === 'header'" :key="index" class="segment-title">
          {{ item.label }}
        </div>
        <!-- 隐藏 -->
        <span
          v-else-if="item.hide || item.hidden"
          :key="index + 1"
          :style="{
            'grid-column-start': 'span 24',
            'grid-column': 'span ' + (item.span || 24),
            'grid-row': 'span ' + (item.row || 1),
            display: item.hidden ? 'none' : ''
          }"
        ></span>
        <!-- 普通的 -->
        <layout
          v-else
          :key="index + 2"
          class="ls-form-item"
          :style="{
            'grid-column-start': 'span 24',
            'grid-column': 'span ' + (item.span || 24),
            'grid-row': 'span ' + (item.row || 1)
          }"
          :item="item"
          :model="model"
          :global="$attrs"
          @mapAnewValidate="anewValidate"
        >
          <!-- 地图走校验anewValidate -->
          <slot :name="item.slotName" v-bind="{ value: model[item.prop], row: item }"></slot>
        </layout>
      </el-col>
      <el-col v-bind="searchBtnSg" class="ls-form-search-btn">
        <slot name="searchBtn"></slot>
        <el-button @click="showMore" v-if="showExpand" link style="padding: 8px 0" type="primary">
          {{ showAll ? '收起' : '展开' }}
          <el-icon v-show="showAll" class="ls-form-search-btn-icon">
            <ArrowUp />
          </el-icon>
          <el-icon v-show="!showAll" class="ls-form-search-btn-icon">
            <ArrowDown />
          </el-icon>
        </el-button>
      </el-col>
    </el-row>
  </el-form>
</template>
<script setup>
import { ArrowUp, ArrowDown } from '@element-plus/icons-vue'
import layout from 'ls-form/src/layout.vue'
import { ref, computed, onMounted } from 'vue'
import { useResizeObserver } from '@vueuse/core'
let emit = defineEmits(['update:config', 'update:model', 'collapse'])
const props = defineProps({
  model: Object,
  config: Array,
  inline: Boolean,
  labelWidth: {
    type: String,
    default: 'auto'
  },
  defaultMediaVal: {
    type: Object,
    default: () => {
      return {
        xs: 24,
        sm: 12, //仅能2个
        md: 8, //仅能3个
        lg: [5, 5, 8, 6], //仅能4个
        xl: [4, 3, 5, 4, 4, 4] //仅能6个
      }
    },
    validator: (valid) => {
      const keyS = ['lg', 'xl', 'md', 'sm', 'xs']
      const keySArrLength = {
        xs: 1,
        sm: 2, //仅能2个
        md: 3, //仅能3个
        lg: 4, //仅能4个
        xl: 6 //仅能6个
      }
      for (let i = 0; i < keyS.length; i++) {
        if (valid[keyS[i]]) {
          const validIsArr = Array.isArray(valid[keyS[i]])
          if (validIsArr) {
            const lengthAccord = valid[keyS[i]].length === keySArrLength[keyS[i]]
            if (!lengthAccord) {
              console.error(`作为数组的${keyS[i]}参数,长度必须为${keySArrLength[keyS[i]]}`)
              return false
            }
          } else {
            if (!Number(valid[keyS[i]])) {
              console.error(`${valid[keyS[i]]}配置不合法`)
              return false
            }
          }
        } else {
          console.error(`缺少${valid[keyS[i]]}配置或不合法`)
          return false
        }
      }
      return true
    }
  }
})
// 默认栅格配置
/*
参数为数值数组或者数值
若为数组则总和须为24 
若为数值则要需要能除尽24
最后一个数值表示操作按钮列宽度
*/
// const defaultMediaVal = {
//   xs: 24,
//   sm: 12,//仅能2个
//   md: 8,//仅能3个
//   lg: [5, 5, 8, 6], //仅能4个
//   xl: [4,3,5,4,4,4] //仅能6个
// }
const getLineWidth = (ty, index) => {
  let width = 0
  if (showAll.value) {
    width = Array.isArray(ty) ? ty[index % ty.length] : ty
  } else {
    width = Array.isArray(ty) ? ty[index % ty.length] : ty
  }
  return width
}
// 计算每行的列数
const lineRankVal = computed(() => {
  const rankVal = {}
  Object.keys(props.defaultMediaVal).forEach((item) => {
    if (Array.isArray(props.defaultMediaVal[item])) {
      rankVal[item] = props.defaultMediaVal[item].length
    } else {
      rankVal[item] = 24 / props.defaultMediaVal[item]
    }
  })
  return rankVal
})
// 展开图标样式控制
const showAll = ref(false)
// 计算操作按钮栏的宽度
const searchBtnSg = computed(() => {
  const { xs, sm, md, lg, xl } = props.defaultMediaVal
  const show = showAll.value
  let btnSm = {
    xs: counterWidth(xs, show),
    sm: counterWidth(sm, show),
    md: counterWidth(md, show),
    lg: counterWidth(lg, show),
    xl: counterWidth(xl, show)
  }
  return btnSm
})
// 计算操作按钮栏宽度
const counterWidth = (configVal, show) => {
  const config = JSON.parse(JSON.stringify(configVal))
  const isArr = Array.isArray(config)
  const propConfigLength = props.config?.length || 0
  let ratio = 24
  // 分两种情况 展开 和收起
  // 先判断配置类型是否为数组
  if (show) {
    // 展开状态 操作栏要补全或独占一行
    if (isArr) {
      const itemConfigLength = config.length
      const blank = propConfigLength % itemConfigLength
      ratio = blank ? config.splice(blank).reduce((a, b) => a + b) : 24
    } else {
      //config 为数值 且是24的因数
      const lineVal = propConfigLength % (24 / config)
      ratio = lineVal ? 24 - lineVal * config : 24
    }
  } else {
    // 收起状态栏仅补全一行
    if (isArr) {
      const itemConfigLength = config.length
      //
      if (propConfigLength < itemConfigLength) {
        // 补全
        ratio = config.splice(propConfigLength).reduce((a, b) => a + b)
      } else {
        ratio = config.pop()
      }
    } else {
      ratio = propConfigLength < 24 / config ? 24 - propConfigLength * config : config
    }
  }
  return ratio
}
const showMore = () => {
  showAll.value = !showAll.value
  emit('collapse', showAll.value)
}
// 根据自定义class获取当前是否有隐藏元素
const showExpand = ref(true)
const getDisplayNone = () => {
  const width = window.innerWidth
  let domListLength = document.querySelectorAll('.ls-search-col-custom').length
  // 若dom+1 数量大于每行的数量则展示
  /*
xs	<768px
sm	≥768px
md	≥992px
lg	≥1200px
xl	≥1920px
*/

  if (width < 768) {
    // 默认可展示2个
    domListLength > 2 ? (showExpand.value = true) : (showExpand.value = false)
    return
  }

  if (width <= 992) {
    domListLength > 1 ? (showExpand.value = true) : (showExpand.value = false)
    return
  }
  if (width < 1200) {
    domListLength > 2 ? (showExpand.value = true) : (showExpand.value = false)
    return
  }
  if (width < 1920) {
    domListLength > 3 ? (showExpand.value = true) : (showExpand.value = false)
    return
  }
  if (width >= 1920) {
    domListLength > 5 ? (showExpand.value = true) : (showExpand.value = false)
    return
  }
}
const rfmediaRow = ref(null)
onMounted(() => {
  useResizeObserver(rfmediaRow, (entries) => {
    const entry = entries[0]
    const { width } = entry.contentRect
    getDisplayNone(width)
  })
})

//结束
const refFormRefs = ref(null)
const anewValidate = (prop) => {
  refFormRefs.value.validateField(prop)
}
const validate = (callback) => {
  refFormRefs.value.validate(callback)
}
const resetFields = () => {
  refFormRefs.value.resetFields()
}
const clearValidate = (props) => {
  refFormRefs.value.clearValidate(props)
}
const setFormConfig = (config, data, prop, attr = 'options') => {
  config.find((item) => item.prop === prop)[attr] = data
  emit('update:config', config)
}
const setFormModel = (formData, data, prop) => {
  formData[prop] = data
  emit('update:model', formData)
}
defineExpose({
  anewValidate,
  validate,
  resetFields,
  clearValidate,
  setFormConfig,
  setFormModel
})
</script>

<style lang="scss" scoped>
.el-col {
  padding-right: 15px;
  min-height: 52px;
}

.ls-show-all {
  .el-col {
    display: block;
  }
}

.ls-form-search-btn-icon {
  margin-left: 10px;
}

.ls-form-search-btn {
  display: flex !important;
  align-items: flex-start;
  justify-content: end;

  :deep(.el-button + .el-button) {
    margin-left: 20px;
  }
}

.ls-search-from {
  :deep(.el-select) {
    width: 100% !important;
  }

  :deep(.el-select-v2) {
    width: 100% !important;
  }

  :deep(.el-form-item) {
    margin-right: 0 !important;
    width: 100% !important;
  }

  :deep(.el-date-editor.el-input) {
    width: 100% !important;
  }

  :deep(.el-input) {
    width: 100% !important;
  }
}

/*
xs	<768px
sm	≥768px
md	≥992px
lg	≥1200px
xl	≥1920px
*/
// /* 小于768  每行展示一个 */
@media only screen and (max-width: 768px) {
  .ls-search-from {
    .ls-show-col:nth-child(n + 3) {
      display: none;
    }
  }
}

/*sm	≥768px 每行两个 */
@media only screen and (min-width: 768px) {
  .ls-search-from {
    .ls-show-col:nth-child(n + 2) {
      display: none;
    }
  }
}

/**= >=992 每行三个 */
@media only screen and (min-width: 992px) {
  .ls-search-from {
    .el-col .ls-show-col:nth-child(n + 3) {
      display: none;
    }

    .ls-show-col:nth-child(-n + 2) {
      display: block;
    }
  }
}

/**= >=1200px 每行四个个 */
@media only screen and (min-width: 1200px) {
  .ls-search-from {
    .ls-show-col:nth-child(n + 4) {
      display: none;
    }

    .ls-show-col:nth-child(-n + 3) {
      display: block;
    }
  }
}

/**= >=1920px 每行五个 */
@media only screen and (min-width: 1920px) {
  body {
    background: rgb(7, 132, 2);
  }

  .ls-search-from {
    .ls-show-col:nth-child(n + 6) {
      display: none;
    }

    .ls-show-col:nth-child(-n + 5) {
      display: block;
    }
  }
}

:deep(.el-form-item__label-wrap) {
  margin-left: 0 !important;
}
</style>
